package cn.bugstack.infrastructure.persistent.repository;


import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.bugstack.domain.strategy.model.entity.StrategyEntity;
import cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity;
import cn.bugstack.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import cn.bugstack.infrastructure.persistent.dao.IStrategyAwardDao;
import cn.bugstack.infrastructure.persistent.dao.IStrategyDao;
import cn.bugstack.infrastructure.persistent.dao.IStrategyRuleDao;
import cn.bugstack.infrastructure.persistent.po.Strategy;
import cn.bugstack.infrastructure.persistent.po.StrategyAward;
import cn.bugstack.infrastructure.persistent.po.StrategyRule;
import cn.bugstack.infrastructure.persistent.redis.IRedisService;
import cn.bugstack.types.common.Constants;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 策略的仓储接口实现类
 */

@Repository
public class StrategyRepository implements IStrategyRepository {

    @Resource
    private IStrategyAwardDao strategyAwardDao;

    @Resource
    private IRedisService redisService;

    @Resource
    private IStrategyDao strategyDao;

    @Resource
    private IStrategyRuleDao strategyRuleDao;


    //根据策略id查询策略奖品表，得到策略配置
    @Override
    public List<StrategyAwardEntity> queryStrategyAwardList(Long strategyId) {

        //先从Redis缓存中获取数据
        String cacheKey = Constants.RedisKey.STRATEGY_AWARD_KEY + strategyId;
        List<StrategyAwardEntity> strategyAwardEntities = redisService.getValue(cacheKey);
        if(strategyAwardEntities != null && !strategyAwardEntities.isEmpty()){
            return strategyAwardEntities;
        }
        //如果缓存中没有 在去数据库中获取数据
        List<StrategyAward> strategyAwards = strategyAwardDao.queryStrategyAwardListByStrategyId(strategyId);
        strategyAwardEntities = new ArrayList<>(strategyAwards.size());
        for(StrategyAward strategyAward : strategyAwards){
            StrategyAwardEntity strategyAwardEntity = StrategyAwardEntity.builder()
                    .strategyId(strategyAward.getStrategyId())
                    .awardId(strategyAward.getAwardId())
                    .awardCount(strategyAward.getAwardCount())
                    .awardRate(strategyAward.getAwardRate())
                    .awardCountSurplus(strategyAward.getAwardCountSurplus())
                    .build();
            strategyAwardEntities.add(strategyAwardEntity);
        }
        //查询数据库后要将这些数据缓存到Redis中
        redisService.setValue(cacheKey, strategyAwardEntities);

        return strategyAwardEntities;
    }


    /**
     * //将 策略奖品搜寻概率表 存到 Redis中
     * @param key
     * @param rateRange
     * @param shuffleStrategyAwardSearchRateTables
     */

    @Override
    public void storeStrategyAwardSearchRateTables(String key, Integer rateRange, HashMap<Integer, Integer> shuffleStrategyAwardSearchRateTables) {
        //1. 存储抽奖策略概率的索引范围
        redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key, rateRange.intValue());
        //2. 存储概率查询表
        Map<Integer, Integer> cacheRateTable = redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key);
        cacheRateTable.putAll(shuffleStrategyAwardSearchRateTables);

    }

    /**
     * 调用仓储层接口 根据 策略id 查询(缓存查) 概率索引范围值rateRange
     * @param strategyId
     * @return
     */
    @Override
    public int getRateRange(Long strategyId) {

        return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId);

    }

    /**
     * 调用仓储层接口 根据 策略id 和 规则权重key 查询(缓存查) 概率索引范围值rateRange
     * @param key
     * @return
     */

    @Override
    public int getRateRange(String key) {
        return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key);
    }

    /**
     * 随机生成一个在范围内的数字用于 抽奖数字，通过策略id 和 这个随机生成的数字 调用仓储层接口 查询(缓存查) 概率表
     * @param strategyId
     * @param randomNum
     * @return
     */
    @Override
    public Integer getStrategyAwardAssemble(Long strategyId, int randomNum) {
        //从map中直接找对应的数据
        return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId, randomNum);

    }


    /**
     * 随机生成一个在范围内的数字用于 抽奖数字，通过 规则权重key 和 这个随机生成的数字 调用仓储层接口 查询(缓存查) 概率表
     * @param key
     * @param randomNum
     * @return
     */
    @Override
    public Integer getStrategyAwardAssemble(String key, int randomNum) {

        //从map中直接找对应的数据
        return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key, randomNum);
    }


    /**
     * 权重规则 配置 —— 符合 rule_weight
     * @param strategyId
     * @return
     */
    @Override
    public StrategyEntity queryStrategyEntityByStrategyId(Long strategyId) {
        //先查redis缓存
        String cacheKey = Constants.RedisKey.STRATEGY_KEY + strategyId;
        StrategyEntity strategyEntity = redisService.getValue(cacheKey);
        if(strategyEntity != null){
            return strategyEntity;
        }
        //缓存没查到 再查数据库
        Strategy strategy = strategyDao.queryStrategyByStrategyId(strategyId);
        return strategyEntity.builder()
                .strategyId(strategyId)
                .strategyDesc(strategy.getStrategyDesc())
                .ruleModels(strategy.getRuleModels())
                .build();

    }


    /**
     * 根据策略id 和 规则权重 查询 策略规则实体类
     * @param strategyId
     * @param ruleWeight
     * @return
     */
    @Override
    public StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleWeight) {
        StrategyRule strategyRuleReq = new StrategyRule();
        strategyRuleReq.setStrategyId(strategyId);
        strategyRuleReq.setRuleModel(ruleWeight);
        StrategyRule strategyRuleRes = strategyRuleDao.queryStrategyRule(strategyRuleReq);
        return StrategyRuleEntity.builder()
                .strategyId(strategyRuleRes.getStrategyId())
                .ruleModel(strategyRuleRes.getRuleModel())
                .ruleValue(strategyRuleRes.getRuleValue())
                .ruleType(strategyRuleRes.getRuleType())
                .ruleDesc(strategyRuleRes.getRuleDesc())
                .awardId(strategyRuleRes.getAwardId())
                .build();

    }


    /**
     * //查询规则配置 在表strategy_rule表中 根据RuleMatterEntity 查询 rule_value
     * @param strategyId
     * @param awardId
     * @param ruleModel
     * @return
     */
    @Override
    public String queryStrategyRuleValue(Long strategyId, Integer awardId, String ruleModel) {

        StrategyRule strategyRule = new StrategyRule();
        strategyRule.setStrategyId(strategyId);
        strategyRule.setAwardId(awardId);
        strategyRule.setRuleModel(ruleModel);
        return strategyRuleDao.queryStrategyRuleValue(strategyRule);

    }


    /**
     * 查询规则配置 在表strategy_rule表中 根据策略id和 规则模型查询 对应策略规则值
     * @param strategyId
     * @param ruleModel
     * @return
     */
    @Override
    public String queryStrategyRuleValue(Long strategyId, String ruleModel) {
        return queryStrategyRuleValue(strategyId, null, ruleModel);
    }

    @Override
    public StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId) {
        StrategyAward strategyAward = new StrategyAward();
        strategyAward.setStrategyId(strategyId);
        strategyAward.setAwardId(awardId);
        String ruleModels = strategyAwardDao.queryStrategyAwardRuleModelVO(strategyAward);
        return StrategyAwardRuleModelVO.builder()
                .ruleModels(ruleModels)
                .build();
    }
}























